package com.smh.demo1.a43;

import com.smh.demo1.common.LogColour;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.GenericApplicationListener;
import org.springframework.core.ResolvableType;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * @author shiminghui
 * @date 2025/5/10 16:06
 * @description: TODO
 */
@Configuration
public class A43 {
    public static void main(String[] args) {
        // 模拟一个事件发布器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A43.class);
        context.publishEvent(new MyEvent(new Object()));
        context.close();

    }

    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext context) {
        return new AbstractApplicationEventMultiCaster() {

//            private final List<ApplicationListener> listeners = new ArrayList<>();

            private final List<GenericApplicationListener> genericListeners = new ArrayList<>();
            @Autowired
            private ThreadPoolTaskExecutor executor;

            // 收集监听器
            @Override
            public void addApplicationListenerBean(String listenerBeanName) {
                // 这个接口没有可以判断监听器是否支持该事件的方法,所以将其封装成另一个接口
                ApplicationListener listener = context.getBean(listenerBeanName, ApplicationListener.class);
//                listeners.add(listener);
                // 获取该监听器支持的事件类型
                ResolvableType generic = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
                System.out.println(generic);
                GenericApplicationListener genericListener = new GenericApplicationListener() {
                    @Override
                    public void onApplicationEvent(ApplicationEvent event) {
                        executor.execute(() -> {
                            listener.onApplicationEvent(event);
                        });
                    }

                    @Override
                    public boolean supportsEventType(ResolvableType eventType) {
                        return generic.isAssignableFrom(eventType);
                    }
                };
                genericListeners.add(genericListener);
//                    context.addApplicationListener(e);  // 它内部就是向发布器添加
            }

            // 调用监听器
            @Override
            public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
                /*listeners.forEach(e -> {
                    e.onApplicationEvent(event);
                });*/
                genericListeners.forEach(listener -> {
                    System.out.println(listener);
                    if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                        listener.onApplicationEvent(event);
                    }
                });
            }
        };
    }

    @Bean
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        return executor;
    }


    // 空实现
    static class AbstractApplicationEventMultiCaster implements ApplicationEventMulticaster {

        @Override
        public void addApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void addApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeApplicationListener(ApplicationListener<?> listener) {

        }

        @Override
        public void removeApplicationListenerBean(String listenerBeanName) {

        }

        @Override
        public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {

        }

        @Override
        public void removeApplicationListenerBeans(Predicate<String> predicate) {

        }

        @Override
        public void removeAllListeners() {

        }

        @Override
        public void multicastEvent(ApplicationEvent event) {

        }

        @Override
        public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {

        }
    }

    static class MyEvent extends ApplicationEvent {

        public MyEvent(Object source) {
            super(source);
        }
    }

    @Component
    static class MyEventListener1 implements ApplicationListener<MyEvent> {

        @Override
        public void onApplicationEvent(MyEvent event) {
            System.out.println(LogColour.Red("MyEventListener1"));
        }
    }

    @Component
    static class MyEventListener2 implements ApplicationListener<MyEvent> {

        @Override
        public void onApplicationEvent(MyEvent event) {
            System.out.println(LogColour.Red("MyEventListener2"));
        }
    }

}
